package org.sith.taskrunner.engine;


import org.sith.taskrunner.api.TaskRunRequest;
import org.sith.taskrunner.api.TaskStateStatus;
import org.sith.taskrunner.api.exceptions.TaskExecutionException;
import org.sith.taskrunner.api.exceptions.TaskInitException;
import org.sith.taskrunner.api.task.Task;
import org.sith.taskrunner.api.task.TaskExecutionResult;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.jms.*;
import java.io.Serializable;
import java.lang.IllegalStateException;
import java.util.Random;


@Stateless(name="TaskExecutorTimerEJB")
public class TaskExecutor implements TaskRunnTimerService {

    private String timerDuration;

    public interface TimerInfo extends Serializable {
        public String getInfo();
    }

    @Resource
    private TimerService timerService;


    @Resource(name = "JmsXA", mappedName = "java:JmsXA")
    private ConnectionFactory connectionFactory;
    @Resource(name = "queue/TaskResultQueue", mappedName = "queue/TaskResultQueue")
    private Queue queue;


    @PostConstruct
    public void postConstruct() {
        timerDuration = PropertiesHolder.getInstance().getProperty("timer.duration");
    }


    @Override
    public void startTimer() {
        TimerInfo timerInfo = new SimpleTimerInfo();
        timerService.createTimer(Integer.valueOf(timerDuration), timerInfo);

    }


    @Timeout
    @Override
    public void onTimout(Timer timer) {

        TaskRunRequest request = null;
        request = TaskRunnerQueue.getInstance().getNextRequest();
        try {
            Task task = request.getTask();
            task.init(request.getInputData());
            TaskExecutionResult taskExecutionResult = task.executeTask();
            request.setResult(taskExecutionResult);
            request.setStateStatus(TaskStateStatus.COMPLETED);
        } catch (TaskInitException e) {
            e.printStackTrace();
            request.setStateStatus(TaskStateStatus.INIT_TASK_FAILED);
        } catch (TaskExecutionException e) {
            e.printStackTrace();
            request.setStateStatus(TaskStateStatus.TASK_EXECUTING_FAILED);
        } catch (Exception ex) {
            request.setStateStatus(TaskStateStatus.INTERNAL_ERROR);
        } finally {
           //TODO
        }


        Connection connection=null;
        try {
            connection = connectionFactory.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer producer = session.createProducer(queue);
            Message message = session.createMessage();
            message.setObjectProperty(TaskRunRequest.TASK_RUNNER_REQUEST,request);
            producer.send(message);

        } catch (JMSException e) {
            throw new IllegalStateException(e);
        }finally {
            if (connection!=null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    throw new IllegalStateException(e);
                }
            }

        }


    }

    private class SimpleTimerInfo implements TimerInfo {
        @Override
        public String getInfo() {
            Random random = new Random();
            return "TaskRunnerTimer:" + System.currentTimeMillis() + ":" + this.hashCode() + ":" + random.nextLong();
        }
    }
}

